package com.sbtr.common.calculate;
//import Jama.EigenvalueDecomposition;
//import Jama.Matrix;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.math3.distribution.TDistribution;
import org.apache.commons.math3.special.Erf;
import org.apache.commons.math3.stat.correlation.PearsonsCorrelation;
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
import org.junit.Test;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class DataAnalysisUtil {

    /**
     * 1.小波变换算法-----------------------------------
     * 可以对给定的数据进行多级小波变换，以分解信号的不同尺度的近似和细节部分。
     * @param data
     * @return
     */
    public double[] dauWaveTrans(double[] data) {
        int levels = 2; // 默认波变换的级数为2
        double[] result = new double[data.length];
        System.arraycopy(data, 0, result, 0, data.length);

        // 两个循环的迭代完成变换计算
        for (int i = 0; i < levels; i++) {
            int halfLength = result.length / 2;
            double[] temp = new double[result.length]; // 临时数组的长度与原数组保持相同

            for (int j = 0; j < halfLength; j++) {
                temp[j] = (result[2 * j] + result[2 * j + 1]) / 2.0;
                temp[halfLength + j] = (result[2 * j] - result[2 * j + 1]) / 2.0;
            }

            // temp数组赋值给result数组
            System.arraycopy(temp, 0, result, 0, result.length);
        }
        return result;
    }

    // 1.小波变换单元测试案例
    @Test
    public void testdauWaveTrans() {
        // 单元测试数据
        double[] testData = {3.5, 4.3, 6.7, 2.5, 8.0, 9.2, 1.2, 5.5};
        // 调用小波变换算法
        double[] transformedData = dauWaveTrans(testData);
        // 输出变换后的结果
        System.out.println("小波变换后的结果为: " + Arrays.toString(transformedData));
    }

    /**
     * 2.相关性分析--------------------------------------
     * 计算Pearson相关系数和显著性水平（p值）
     * @param data1            第一组数据
     * @param data2            第二组数据
     * @return 相关系数和显著性水平的结果数组
     */
    public  static JSONObject dauCorrelation(double[] data1, double[] data2) {

        // sigLevel 显著性水平参数
        double sigLevel = 0.05;

        // 计算Pearson相关系数
        PearsonsCorrelation correlation = new PearsonsCorrelation();
        double pn = correlation.correlation(data1, data2);

        // 计算自由度
        int df = data1.length - 2;

        // 计算p值
        TDistribution tDistribution = new TDistribution(df);
        double tStatistic = pn * Math.sqrt((data1.length - 2) / (1 - pn * pn));
        double pValue = 2 * (1 - tDistribution.cumulativeProbability(Math.abs(tStatistic)));

        String result = "在显著性水平【"+sigLevel+"】下";
        if (pValue < sigLevel) {
            result += "存在相关性";
        } else {
            result += "不存在相关性";
        }
        // 创建JSONObject对象并填充数据
        JSONObject data = new JSONObject();
        data.put("Pearson相关系数", pn);
        data.put("P-值", pValue);
        data.put("自由度", df);
        data.put("是否相关", result);
        return data;
    }

    // 2.相关性分析单元测试
    @Test
    public void testdauCorrelation() {

        double[] data1 = {1, 9, 3, 6, 4};
        double[] data2 = {9, 5, 7, 4, 6};

        JSONObject jsonObject = dauCorrelation(data1, data2);
        System.err.println(jsonObject);
    }

    /**
     * 3.Fisher判别分析算法-----------------------------------
     * @param classA：待分析数组
     * @param classB: 待分析数组
     * @return
     */
    public static double dauFisherAnalysis(double[] classA, double[] classB) {
        // 计算类A和类B的均值
        double meanA = calculateMean(classA);
        double meanB = calculateMean(classB);

        // 计算类A和类B的方差
        double varianceA = calculateVariance(classA, meanA);
        double varianceB = calculateVariance(classB, meanB);

        // 计算Fisher判别分析结果
        double result = Math.abs(meanA - meanB) / Math.sqrt(varianceA + varianceB);
        return result;
    }
    // 均值计算
    public static double calculateMean(double[] data) {
        double sum = 0;
        for (double value : data) {
            sum += value;
        }
        return sum / data.length;
    }

    // 计算方差
    public static double calculateVariance(double[] data, double mean) {
        double sumSquaredDiff = 0;
        for (double value : data) {
            sumSquaredDiff += Math.pow((value - mean), 2);
        }
        return sumSquaredDiff / data.length;
    }

    /**
     * 3.Fisher判别分析算法单元测试案例
     */
    @Test
    public void testdauFisherAnalysis() {
        // 单元测试数据
        double[] classAData = {1.2, 1.5, 1.8, 2.0, 2.3};
        double[] classBData = {2.5, 3.0, 3.5, 4.0, 4.5};

        // 调用Fisher判别分析方法
        double result = dauFisherAnalysis(classAData, classBData);
        System.out.println("Fisher判别分析结果为: " + result);
    }

    /**
     * 4.互信息的聚类相似性度量算法-----------------------------------
     * 计算的是两个特征之间的互信息值，互信息值越大说明这两个特征之间的相关性越强。
     * @param X
     * @param Y
     * @return
     */
    public static double dauCalMIValue(Map<String, Integer> X, Map<String, Integer> Y) {
        double mi = 0.0;
        int total = getTotalCount(X);

        for (Map.Entry<String, Integer> entryX : X.entrySet()) {
            String featureX = entryX.getKey();
            int countX = entryX.getValue();

            for (Map.Entry<String, Integer> entryY : Y.entrySet()) {
                String featureY = entryY.getKey();
                int countY = entryY.getValue();

                int countXY = getCountXY(featureX, featureY, X, Y);

                if (countXY > 0) {
                    double pX = (double) countX / total;
                    double pY = (double) countY / total;
                    double pXY = (double) countXY / total;

                    mi += pXY * Math.log(pXY / (pX * pY));
                }
            }
        }

        return mi;
    }

    // 统计总词频
    public static int getTotalCount(Map<String, Integer> map) {
        int total = 0;
        for (int count : map.values()) {
            total += count;
        }
        return total;
    }
    // 统计两个特征同时出现的次数
    public static int getCountXY(String featureX, String featureY, Map<String, Integer> X, Map<String, Integer> Y) {
        // 为了简化示例，这里假设特征X和特征Y是独立的，实际应用中需要根据具体情况编写计算逻辑
        return Math.min(X.getOrDefault(featureX, 0), Y.getOrDefault(featureY, 0));
    }

    /**
     * 4.互信息算法 单元测试案例
     */
    @Test
    public void testdauCalMIValue() {

        Map<String, Integer> X = new HashMap<>();
        X.put("特征1", 5);
        X.put("特征2", 10);
        X.put("特征3", 15);

        Map<String, Integer> Y = new HashMap<>();
        Y.put("特征1", 8);
        Y.put("特征2", 12);
        Y.put("特征3", 10);

        double mutualInformation = dauCalMIValue(X, Y);
        System.out.println("互信息值：" + mutualInformation);
    }

    /**
     * 5.Z-Score标准化算法-----------------------------------
     * 对给定数据进行Z-Score标准化处理
     * @param data 待标准化的数据
     * @return 标准化后的数据
     */
    public static double[] duaNormalize(double[] data) {
        double mean = 0.0;
        double stdDev = 0.0;
        int length = data.length;

        // 计算均值
        for (double num : data) {
            mean += num;
        }
        mean /= length;

        // 计算方差
        for (double num : data) {
            stdDev += Math.pow(num - mean, 2);
        }
        stdDev /= (length - 1); // 使用总体标准差
        stdDev = Math.sqrt(stdDev);

        // 进行Z-Score标准化计算
        double[] normalizedData = new double[length];
        for (int i = 0; i < length; i++) {
            normalizedData[i] = (data[i] - mean) / stdDev;
        }
        return normalizedData;
    }

    /**
     *  5.Z-Score标准化算法单元测试案例
     */
    @Test
    public void testduaNormalize() {
        // 示例数据
        double[] data = {1.0, 2.0, 3.0, 4.0, 5.0};
        // 调用Z-Score标准化方法
        double[] normalizedData = duaNormalize(data);
        // 打印Z-Score标准化后的数据
        System.out.println("Z-Score标准化后的数据:");
        for (double d : normalizedData) {
            System.out.println(d);
        }
    }

    /**
     * 6.秩和检验算法-----------------------------------
     * @param x：样本组一
     * @param y：样本组二
     * @return
     */
    public static JSONObject duaRankSum(double[] x, double[] y) {
        // sigLevel 显著性水平参数
        double sigLevel = 0.05;
        int n1 = x.length;
        int n2 = y.length;
        double[] combined = new double[n1 + n2];
        System.arraycopy(x, 0, combined, 0, n1);
        System.arraycopy(y, 0, combined, n1, n2);
        Arrays.sort(combined);

        int[] ranks = new int[n1 + n2];
        for (int i = 0; i < n1 + n2; i++) {
            int rank = 1;
            for (int j = 0; j < n1 + n2; j++) {
                if (combined[j] < combined[i]) {
                    rank++;
                }
            }
            ranks[i] = rank;
        }

        double sum1 = 0;
        for (int i = 0; i < n1; i++)
            sum1 += ranks[i];

        int N = n1 + n2;
        int T = (int)(Math.min(sum1, N * (N + 1) / 2 - sum1));

        double mu_T = n1 * (N + 1) / 2;
        double sigma_T = Math.sqrt(n1 * n2 * (N + 1) / 12.0);
        double u = (T - mu_T) / sigma_T;
        double p_value = 2 * Math.min(Math.abs(0.5 - 0.5 * Erf.erf(u / Math.sqrt(2))), Math.abs(0.5 + 0.5 * Erf.erf(u / Math.sqrt(2))));

        String result = "在显著性水平【"+sigLevel+"】下";
        if (p_value < sigLevel) {
            result += "接受原假设";
        } else {
            result += "拒绝原假设";
        }
        // 创建JSONObject对象并填充数据
        JSONObject data = new JSONObject();
        data.put("P-值", p_value);
        data.put("检验统计量", u);
        data.put("是否拒绝", result);
        return data;
    }

    // 6.秩和检验算法 单元测试案例
    @Test
    public void testRankSum() {

        double[] x = {1, 2, 3, 4, 5};
        double[] y = {6, 7, 8, 9, 10};
        JSONObject jsonObject = duaRankSum(x, y);
        System.err.println(jsonObject);
    }

    // ----------------------标准差、方差、峰值、平均数等判断---------------------------

    /**
     * 7.基于标准差值的状态评估算法
     * 标准差的比较判断 ，给定值大于标准差，即返回值设置为1.
     * @param numbers
     * @param vartest
     * @return
     */
    public static  int dauBysigma(double[] numbers) {
        double vartest = 2.0;

        double sum = 0;
        int result = 0;
        double agvs = 0.0;
        double vt = 0.0;
        double sigma = 0.0;
        for(int i = 0; i< numbers.length;++i)
            agvs += numbers[i];

        agvs = agvs/numbers.length;
        for(int j =0; j<numbers.length; ++j)
            vt += (numbers[j]-agvs)* (numbers[j]-agvs);

        vt = vt/(numbers.length*1.0);
        sigma = Math.sqrt(vt);
        if(vartest >sigma)
            result =1;
        return  result;
    }

    /****
     * 8.基于参数均值的故障诊断算法
     * 按照设备功率进行分析，如果平均功率超过
     * @param numbers
     * @param drage
     * @return p平均值大于给定值则置为1，否则为0；
     */
    public static int dauByPower(double[] numbers){
        double drage = 150.0;

        double sum =0;
        for(int i = 0; i< numbers.length; ++i)
            sum += numbers[i];

        double ave = sum/(numbers.length*1.0);
        return ave>drage?1:0;
    }

    /***
     * 9.基于参数最大值故障诊断算法
     *  按照设备的温度进行分析，如果有一个超过给定的温度值，则报警返回1。
     * @param numbers
     * @param drage
     * @return
     */
    public static  int duaByTemp(double[] numbers) {
        double drage = 30.0;

        double sum =0;
        int result = 0;
        double tempmax = numbers[0];
        for(int i = 1; i< numbers.length;++i) {
            if(numbers[i] > tempmax)
                tempmax = numbers[i];
        }
        if(drage <tempmax)
            result  = 1;
        return  result;
    }


    /***
     * 10.基于方差值的状态评估算法
     方差比较的判断，给定值大于方差即返回值设置为1.
     ***/
    public static  int duaByVar(double[] numbers) {
        double verTest = 2.0;

        double sum = 0;
        int result = 0;
        double agvs = 0.0;
        double vt = 0.0;

        for(int i = 0; i< numbers.length;++i)
            agvs += numbers[i];

        agvs = agvs/numbers.length;
        for(int j =0; j<numbers.length; ++j)
            vt += (numbers[j]-agvs)* (numbers[j]-agvs);

        vt = vt/(numbers.length*1.0);
        if(verTest >vt)
            result =1;
        return  result;
    }

    /***
     * 11.基于峰峰值的故障诊断算法
     *  峰峰值进行比较，如果峰峰值大于给定值，返回1，否则返回0.
     * @param numbers
     * @param vartTest
     * @return
     */
    public static int duaBypp(double[] numbers) {
        double vartTest = 5.0;

        double sum = 0;
        int result =0;
        double agvs = 0;
        double max_temp=numbers[0];
        double min_temp = numbers[0];
        double vt =0.0;

        for( int i = 1; i< numbers.length;++i) {
            if(max_temp< numbers[i])
                max_temp= numbers[i];

            if(min_temp> numbers[i])
                min_temp = numbers[i];
        }
        vt = max_temp -min_temp;
        if(vt> vartTest)
            result = 1;

        return  result;
    }

    /**
     * 12.基于均值的状态评估算法
     * 均值比较，如果均值大于给定的值，则返回1，否则返回0.
     * @param numbers
     * @param drage
     * @return
     */
    public static int duaByave(double[] numbers) {
        double drage = 35.0;

        double sum = 0;
        for(int i = 0; i<numbers.length;++i)
            sum+= numbers[i];

        double ave = sum/(numbers.length*1.0);
        return  ave > drage? 1:0;
    }

    /**
     * 13.基于最大值的状态评估算法
     * 最大值判断，如果最大值都比给定的值小，则返回1.否则返回0.
     * @param numbers
     * @param drage
     * @return
     */
    public static  int duaByMax(double [] numbers) {
        double drage = 20.0;

        double sum = 0;
        int result = 0;
        double tempmax = numbers[0];
        for(int i = 0; i< numbers.length; ++i) {
            if(numbers[i] > tempmax )
                tempmax = numbers[i];
        }
        if(drage > tempmax)
            result =1;
        return result;
    }

    /**
     * 14.基于最小值的状态评估算法
     * @param numbers
     * @param drage
     * @return
     */
    public static  int  duaByMin(double[] numbers) {
        double drage = 1.0;

        double sum = 0;
        int result = 0;
        double tempmin = numbers[0];
        for(int i = 0; i< numbers.length; ++i) {
            if(numbers[i] < tempmin )
                tempmin = numbers[i];
        }
        if(drage < tempmin)
            result =1;
        return result;
    }

    // 7.基于标准差值的状态评估算法 单元测试
    @Test
    public void testdauBysigma() {
        // 输入数据
        double[] numbers = {5.0, 7.0, 9.0, 11.0, 13.0};
        // 调用被测方法
        int result = dauBysigma(numbers);
        // 打印输出结果端
        System.out.println("dauBysigma 测试结果: " + result);
    }

    // 8.基于参数均值的故障诊断算法
    @Test
    public void testdauByPower() {
        // 输入数据
        double[] numbers = {100.0, 200.0, 300.0};
        // 调用被测方法
        int result = dauByPower(numbers);
        // 打印输出结果
        System.out.println("dauByPower 测试结果: " + result);
    }

    // 9.基于参数最大值故障诊断算法
    @Test
    public void testduaByTemp() {
        // 输入数据
        double[] numbers = {25.0, 27.0, 29.0, 26.0, 28.0};
        // 调用被测方法
        int result = duaByTemp(numbers);
        // 打印输出结果
        System.out.println("duaByTemp 测试结果: " + result);
    }

    /***
     10.基于方差值的状态评估算法
     ***/
    @Test
    public void testduaByVar() {
        // 输入数据
        double[] numbers = {1.0, 2.0, 3.3, 4.0, 4.2};
        // 调用被测方法
        int result = duaByVar(numbers);
        // 打印输出结果
        System.out.println("duaByVar 测试结果: " + result);
    }

    // 11.基于峰峰值的故障诊断算法
    @Test
    public void testduaBypp() {
        // 输入数据
        double[] numbers = {3.0, 8.0, 5.0, 12.0, 7.0};
        // 调用被测方法
        int result = duaBypp(numbers);
        // 打印输出结果
        System.out.println("duaBypp 测试结果: " + result);
    }

    // 12.基于均值的状态评估算法
    @Test
    public void testduaByave() {
        // 输入数据
        double[] numbers = {10.0, 20.0, 30.0, 40.0, 50.0};
        // 调用被测方法
        int result = duaByave(numbers);
        // 打印输出结果
        System.out.println("duaByave 测试结果: " + result);
    }

    // 13.基于最大值的状态评估算法单元测试
    @Test
    public void testduaByMax() {
        // 输入数据
        double[] numbers = {5.0, 8.0, 15.0, 9.0, 11.0};
        // 调用被测方法
        int result = duaByMax(numbers);
        // 打印输出结果
        System.out.println("duaByMax 测试结果: " + result);
    }

    // 14.基于最小值的状态评估算法单元测试
    @Test
    public void testduaByMin() {
        double[] testArray = {3.5, 2.0, 4.8, 1.2, 5.6};
        int actualResult = duaByMin(testArray);
        System.out.println("duaByMin 测试结果: " + actualResult);
    }
    /**
     * 15.最大归一化算法-----------------------------------
     * 对给定数据进行最大值归一化处理
     * @param data 待归一化的数据
     * @return 归一化后的数据
     */
    public static double[] duaNorMaxValue(double[] data) {
        // 初始化最大值为Double.MIN_VALUE
        double max = Double.MIN_VALUE;
        // 寻找最大值
        for (double d : data) {
            if (d > max)
                max = d;
        }
        // 进行归一化计算
        double[] normalizedData = new double[data.length];
        for (int i = 0; i < data.length; i++) {
            normalizedData[i] = data[i] / max;
        }
        return normalizedData;
    }

    // 15.最大归一化算法单元测试
    @Test
    public void testduaNorMaxValue() {
        // 示例数据
        double[] data = {100, 200, 300, 400, 500};
        // 调用最大值归一化方法
        double[] normalizedData = duaNorMaxValue(data);
        // 打印归一化后的数据
        System.out.println("归一化后的数据:");
        for (double d : normalizedData) {
            System.out.println(d);
        }
    }

    /**
     *  16.最大最小值归一化算法-----------------------------------
     * 对给定数据进行最大最小值归一化处理
     * @param data 待归一化的数据
     * @return 归一化后的数据
     */
    public static double[] duaNorMinMax(double[] data) {
        // 初始化最大最小值
        double max = Double.MIN_VALUE;
        double min = Double.MAX_VALUE;
        // 寻找最大最小值
        for (double d : data) {
            if (d > max)
                max = d;

            if (d < min)
                min = d;
        }
        // 进行归一化计算
        double[] normalizedData = new double[data.length];
        for (int i = 0; i < data.length; i++) {
            normalizedData[i] = (data[i] - min) / (max - min);
        }
        return normalizedData;
    }

    //  16.最大最小值归一化算法单元测试
    @Test
    public void testduaNorMinMax() {
        // 示例数据
        double[] data = {1.0, 2.0, 3.0, 4.0, 5.0};
        // 调用最大最小值归一化方法
        double[] normalizedData = duaNorMinMax(data);
        // 打印归一化后的数据
        System.out.println("归一化后的数据:");
        for (double d : normalizedData) {
            System.out.println(d);
        }
    }

    /**
     * 17.TT检验算法--------------------------------------
     * 实现双样本t检验算法的代码
     * @param sample1:样本数据
     * @param sample2：对比数据
     * // 设置显著性水平为0.05（通常是0.05或0.01）
     * @return
     */
    public static JSONObject duaTTest(double[] sample1, double[] sample2) {

        // 设置显著性水平为0.05（通常是0.05或0.01）
        double sigLevel = 0.05;

        Map<String,Object> resultMap = new HashMap<String,Object>();
        // 计算 t 值
        double tValue = calculateTValue(sample1, sample2);
        // 获取自由度
        int df = sample1.length + sample2.length - 2;
        // 根据自由度和显著性水平查找临界值
        double criticalValue = getCriticalValue(df, sigLevel);
        // 比较 t 值和临界值
        String result = "在显著性水平【"+sigLevel+"】下";
        if (Math.abs(tValue) > criticalValue){
            result += "数据集的均值发生了显著变化";
        }else{
            result += "数据集的均值未发生显著变化";
        }
        // 创建JSONObject对象并填充数据
        JSONObject data = new JSONObject();
        data.put("t-值", tValue);
        data.put("自由度", df);
        data.put("变化情况", result);
        return data;
    }

    /**
     * 计算标准差
     * @param data 样本数据集
     * @return 标准差
     */
    public static double getStdDev(double[] data) {
        DescriptiveStatistics stats = new DescriptiveStatistics(data);
        return stats.getStandardDeviation();
    }

    /**
     * 计算 t 值
     * @param sample1  第一个数据集
     * @param sample2 第二个数据集
     * @return t 值
     */
    public static double calculateTValue(double[] sample1, double[] sample2) {

        // 计算样本数据集的均值和标准差
        double mean1 = new DescriptiveStatistics(sample1).getMean();
        double stdDev1 = getStdDev(sample1);
        double mean2 = new DescriptiveStatistics(sample2).getMean();
        double stdDev2 = getStdDev(sample2);
        Integer n1 = sample1.length;
        Integer n2 = sample2.length;

        double numerator = mean1 - mean2;
        double denominator = Math.sqrt(Math.pow(stdDev1, 2) / n1 + Math.pow(stdDev2, 2) / n2);
        return numerator / denominator;
    }

    /**
     * 获取 t 分布的临界值
     * @param df    自由度
     * @param alpha 显著性水平
     * @return t 分布的临界值
     */
    public static double getCriticalValue(int df, double alpha) {
        TDistribution tDist = new TDistribution(df);
        return tDist.inverseCumulativeProbability(1 - alpha / 2);
    }

    // 17.T检验测试情况
    @Test
    public void testduaTTest() {

        // 样本数据集1，对照组数据集
        double[] sample1 = {1.2, 2.5, 3.1, 2.8, 2.6, 2.9, 3.4, 2.7, 2.7, 2.8};
        // 样本数据集2，测试组数据集
        double[] sample2 = {2.1, 1.8, 3.3, 2.5, 3.1, 3.3, 2.2, 2.9, 3.0, 2.5};
        JSONObject jsonObject = duaTTest(sample1,sample2);
        System.err.println(jsonObject);
    }

//    /**
//     *18.PCA主成分分析算法-----------------------------------
//     * @param inputData：待处理数据
//     * @return
//     */
//    public static double[][] duaPCA(double[][] inputData) {
//        int numComponents = 2; // 保留的主成分的数量
//        // 创建数据矩阵
//        Matrix data = new Matrix(inputData);
//        // 计算协方差矩阵
//        Matrix covarianceMatrix = calculateCovarianceMatrix(data);
//
//        // 计算协方差矩阵的特征值和特征向量
//        EigenvalueDecomposition decomposition = covarianceMatrix.eig();
//        Matrix eigenVectors = decomposition.getV();
//
//        // 使用Matrix选择前k个特征向量
//        Matrix selectedEigenVectors = eigenVectors.getMatrix(0, eigenVectors.getColumnDimension() - 1, 0, numComponents - 1);
//
//        // 使用Matrix将数据投影到主成分空间
//        Matrix projectedData = data.times(selectedEigenVectors);
//
//        double[][] projectedDataArray = projectedData.getArray();
//        return projectedDataArray;
//    }
//
//    /**
//     * 计算协方差矩阵
//     * @param data:协方差矩阵
//     * @return
//     */
//    private static Matrix calculateCovarianceMatrix(Matrix data) {
//        int numSamples = data.getRowDimension();
//        Matrix covarianceMatrix = new Matrix(data.getColumnDimension(), data.getColumnDimension());
//        // 计算每对特征之间的协方差
//        for (int i = 0; i < data.getColumnDimension(); i++) {
//            for (int j = i; j < data.getColumnDimension(); j++) {
//                double cov = 0.0;
//                for (int k = 0; k < numSamples; k++) {
//                    cov += (data.get(k, i) - calculateMean(data, i)) * (data.get(k, j)
//                            - calculateMean(data, j));
//                }
//                cov /= numSamples - 1;
//                covarianceMatrix.set(i, j, cov);
//                covarianceMatrix.set(j, i, cov);
//            }
//        }
//
//        return covarianceMatrix;
//    }
//
//    // 计算平均值
//    private static double calculateMean(Matrix data, int column) {
//        int numSamples = data.getRowDimension();
//        double sum = 0.0;
//        for (int i = 0; i < numSamples; i++) {
//            sum += data.get(i, column);
//        }
//        return sum / numSamples;
//    }

//    // 18.PCA主成分分析算法 测试情况
//    @Test
//    public void testduaPCA() {
//        // 示例数据
//        double[][] inputData = {
//                {1.0, 2.0, 3.0},
//                {4.0, 5.0, 6.0},
//                {7.0, 8.0, 9.0},
//                {10.0, 11.0, 12.0}
//        };
//        // 执行主成分分析
//        double[][] projectedDataArray = duaPCA(inputData);
//        // 打印投影后的数据
//        System.out.println(JSON.toJSONString(projectedDataArray));
//    }

    /**
     * 19.中心化标准化算法-----------------------------------
     * @param data
     * @return
     */
    public static double[] duaCentralization(double[] data) {
        double[] result = new double[data.length];
        double sum = 0;
        for (int i = 0; i < data.length; i++) {
            sum += data[i];
        }
        double avg = sum / data.length;
        double sum2 = 0;
        for (int i = 0; i < data.length; i++) {
            sum2 += Math.pow(data[i] - avg, 2);
        }
        //计算data数组的标准差
        double std = Math.sqrt(sum2 / data.length);
        for (int i = 0; i < data.length; i++) {
            result[i] = (data[i] - avg) / std; // 中心化标准化公式
        }
        return result;
    }

    // 19.中心化标准化算法 单元测试
    @Test
    public void testduaCentralization() {
        double[] data = {1, 2, 3, 4, 5};
        // 调用中心化标准化方法
        double[] normalizedData = duaCentralization(data);
        // 打印中心化标准化后的数据
        System.out.println("中心化标准化后的数据:");
        for (double d : normalizedData) {
            System.out.println(d);
        }
    }

}
